<!doctype html>
<html lang="en">
	<head>
		<title>How it works</title>
		<meta charset="utf-8">
		<!-- <link href="stylesheets/bootstrap.min.css" rel="stylesheet" type="text/css"> -->
        <link type="text/css" rel="stylesheet" href="stylesheets/materialize.css"  media="screen,projection"/> 

		<style>
			/*@import url(https://fonts.useso.com/css?family=Lato:300italic,700italic,300,700);*/

			body {
				/*font-family: 'Lato';*/
				background-color: #ff5252;
				margin: 0px auto;
			}
			
			#overlay, #canvasel {
				position: absolute;
				top: 0px;
				left: 0px;
				-o-transform : scaleX(-1);
				-webkit-transform : scaleX(-1);
				transform : scaleX(-1);
				-ms-filter : fliph; /*IE*/
				filter : fliph; /*IE*/
			}

			#videoel {
				-o-transform : scaleX(-1);
				-webkit-transform : scaleX(-1);
				transform : scaleX(-1);
				-ms-filter : fliph; /*IE*/
				filter : fliph; /*IE*/
			}

			#container, #webglcontainer {
				position : relative;
				width : 370px;
				height : 346px;
				/*margin : 0px auto;*/
			}
			
			#content {
				margin-top : 70px;
				margin-left : 100px;
				margin-right : 100px;
				max-width: 950px;
			}
			
			#sketch {
				display: none;
			}
			
			#filter {
				display: none;
			}

			h2 {
				font-weight : 400;
			}
			
			.nogum {
				display : none;
			}
			
			.btn {
				/*font-family: 'Lato';*/
				font-size: 16px;
			}

			.hide {
				display : none;
			}

			.nohide {
				display : block;
			}
		</style>
		<script type="text/javascript">

			var _gaq = _gaq || [];
			_gaq.push(['_setAccount', 'UA-32642923-1']);
			_gaq.push(['_trackPageview']);

			(function() {
				var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
				ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
				var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
			})();

		</script>
	</head>	
	<body>
		<script src="javascripts/dat.gui.min.js"></script>
		<script src="javascripts/utils.js"></script>
		<script src="javascripts/numeric-1.2.6.min.js"></script>
		<script src="javascripts/mosse.js"></script>
		<script src="javascripts/jsfeat-min.js"></script>
		<script src="javascripts/frontalface.js"></script>
		<script src="javascripts/jsfeat_detect.js"></script>
		<script src="javascripts/left_eye_filter.js"></script>
		<script src="javascripts/right_eye_filter.js"></script>
		<script src="javascripts/nose_filter.js"></script>
		<script src="javascripts/model_pca_20_svm.js"></script>
		<script src="javascripts/clm.js"></script>
		<script src="javascripts/svmfilter_webgl.js"></script>
		<script src="javascripts/svmfilter_fft.js"></script>
		<script src="javascripts/mossefilter.js"></script>
		<script src="javascripts/Stats.js"></script>
		<script src="javascripts/face_deformer.js"></script>
        <script type="text/javascript" src="javascripts/jquery.min.js"></script>

		<nav>
            <div class="nav-wrapper">
              <a href="/emotion" class="brand-logo center">Emonitor</a>
              <ul id="nav-mobile" class=" hide-on-med-and-down">
                <li class="left"><a class="modal-trigger" href="#modal1"><i class="mdi-action-account-child"></i></a></li>
                <li class="right"><a class="modal-trigger" href="#modal2"><i class="mdi-action-assignment"></i></a></li>  
                <!-- <li class="right"><a class="modal-trigger" href="#"><i class="mdi-av-videocam"></i></a></li>                 -->
              </ul>
            </div>
        </nav>

  <!-- Modal Structure -->
  <div id="modal1" class="modal">
    <div class="modal-content">
      <div class="col s12 m8 offset-m2 l6 offset-l3">
        <div class="card-panel grey lighten-5 z-depth-1">
          <div class="row valign-wrapper">
            <div class="col s4">
              <img src="images/xiong.jpg" alt="" class="circle responsive-img"> 
            </div>
            <div class="col s10">
              <span class="black-text">
                <span class="mdi-social-person red-text accent-2"> Name:  </span>Eric Xiong<br>
                <span class="mdi-social-school red-text accent-2"> School:  </span>Chinese Academy of Sciences<br>
                <span class="mdi-action-book red-text accent-2"> Role:  </span>Engineer, Data Science Graduate Student<br>
                <span class="mdi-action-extension red-text accent-2"> Skills&Hobbies:  </span>Data Visualization, Nodejs, Computer Vision, Raspberry Pi, Intel Edison, Arduino<br>
                <span class="mdi-communication-email red-text accent-2"> Email:  </span>xiongzhp@outlook.com<br>
              </span>
            </div>
          </div>

          <div class="row valign-wrapper">
            <div class="col s4">
              <img src="images/Tao.jpg" alt="" class="circle responsive-img"> <!-- notice the "circle" class -->
            </div>
            <div class="col s10">
              <span class="black-text">
                <span class="mdi-social-person red-text accent-2"> Name:  </span>Tony Zhong<br>
                <span class="mdi-social-school red-text accent-2"> School:  </span>Chinese Academy of Sciences<br>
                <span class="mdi-action-book red-text accent-2"> Role:  </span>Designer, Pharmaceutics Graduate Student<br>
                <span class="mdi-action-extension red-text accent-2"> Skills&Hobbies:  </span>Google Materia Design, SketchUp, 3D printing, Solidworks, AI, Final Cut<br>
                <span class="mdi-communication-email red-text accent-2"> Email:  </span>575313339@qq.com
              </span>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="modal-footer">
      <a href="#!" class=" modal-action modal-close waves-effect waves-green btn-flat">close</a>
    </div>
  </div>
  <!-- Modal Structure -->
  <div id="modal2" class="modal modal-fixed-footer">
    <div class="modal-content">
      <h5>Introduction</h5>
      <p>This is a javascript implementation of face tracking and emotion detection, we built it with nodejs, emit extreme emotions with socket.io and store realtime quantified emotion data into mongodb. In addition, we figure out the mean of each quantified emotion(unhappy, happy, surprise) and the counts of extreme emotions in every minute, hours, or time span you want using mapreduce(the technique utilized in Hadoop and Spark). Above all, we defined a new concept, Emotion Index, which is caculated in combination of the mean of quantified emotions and the counts of extreme emotions.</p><br>
      <h5>To-Do</h5>      
      <p>We made it run smoothly on Intel Edison and Raspeberry Pi, and we will get use of GPIO to make the hardware interact with you whenever extreme emotions are detected.</p>
      <p>We also plan to make an easy access hardware, which is capable of collecting as much emotion data as possible. For one thing, with the hardware, we can easily collect emotion data from people with psychological problems every day in psychology research, so we can get better understanding of mental disorders, like autism, depression and anxiety. For another, we can apply it in shopping mall for realtime feedback of products from visitors.</p>
      <p>What's your ideas? Contact us xiongzhp@outlook.com.</p>
    </div>
    <div class="modal-footer">
      <a href="#!" class="modal-action modal-close waves-effect waves-green btn-flat">Close</a>
    </div>
  </div>

		<div id="content">
			<h5>How it works</h5>
			<div id="container" class="nohide">
				<video id="videoel" width="370" height="288" preload="auto"></video>
				<canvas id="canvasel" width="370" height="288" class="hide"></canvas>
				<canvas id="overlay" width="370" height="288"></canvas>
			</div>
			<div id="webglcontainer" class="hide">
				<canvas id="webgl" width="306" height="342"></canvas>
			</div>
			<br/>
<!-- 			<div id="buttons">
				<input class="btn" type="button" value="wait, loading video" disabled="disabled" onclick="startVideo()" id="startbutton"></input>
			</div> -->
			    <div id="controls">
                    <a id="startbutton" class="waves-effect waves-light btn" onclick="startDemo()">Start</a>
                </div>
			<p id="score"></p>
			
			<p id='gUMMessage'></p>
			<script>
				var vid = document.getElementById('videoel');
				var overlay = document.getElementById('overlay');
				var overlayCC = overlay.getContext('2d');
				
				var ctrack = new clm.tracker();
				ctrack.init(pModel);
				
				stats = new Stats();
				stats.domElement.style.position = 'absolute';
				stats.domElement.style.top = '0px';
				document.getElementById('container').appendChild( stats.domElement );
				
				function enablestart() {
					var startbutton = document.getElementById('startbutton');
					startbutton.value = "start";
					startbutton.disabled = null;
				}

				var insertAltVideo = function(video) {
					
					if (supports_video()) {
						if (supports_ogg_theora_video()) {
							video.src = "./media/franck.ogv";
						} else if (supports_h264_baseline_video()) {
							alert("no mp4 video :(");
							//video.src = "./media/capture4.mp4";
						} else {
							return false;
						}
						//video.play();
						return true;
					} else return false;
				}
				
				var insertAltImage = function() {
					var canvas = document.getElementById('canvasel');
					var cc = canvas.getContext('2d');
					var img = new Image();
					img.onload = function() {
						cc.drawImage(img, 0, 0, 370, 288);
					};
					img.src = './media/franck_02221.jpg';  
					vid.className = "hide";
					vid = canvas;
					canvas.className = "nohide";
					
					var startbutton = document.getElementById('startbutton');
					startbutton.onclick = function() {
						ctrack.start(vid);
						drawLoop();
					}
					startbutton.value = "start";
					startbutton.disabled = null;
				}
				
				// check whether browser supports webGL
				var webGLContext;
				var webGLTestCanvas = document.createElement('canvas');
				if (window.WebGLRenderingContext) {
					webGLContext = webGLTestCanvas.getContext('webgl') || webGLTestCanvas.getContext('experimental-webgl');
					if (!webGLContext || !webGLContext.getExtension('OES_texture_float')) {
						webGLContext = null;
					}
				}
				if (webGLContext == null) {
					alert("Your browser does not seem to support WebGL. Unfortunately this face deformation example depends on WebGL, so you'll have to try it in another browser. :(");
				}
				
				navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
				window.URL = window.URL || window.webkitURL || window.msURL || window.mozURL;
				// check for camerasupport
				if (navigator.getUserMedia) {
					// set up stream
					
					var videoSelector = {video : true};
					if (window.navigator.appVersion.match(/Chrome\/(.*?) /)) {
						var chromeVersion = parseInt(window.navigator.appVersion.match(/Chrome\/(\d+)\./)[1], 10);
						if (chromeVersion < 20) {
							videoSelector = "video";
						}
					};
				
					navigator.getUserMedia(videoSelector, function( stream ) {
						if (vid.mozCaptureStream) {
							vid.mozSrcObject = stream;
						} else {
							vid.src = (window.URL && window.URL.createObjectURL(stream)) || stream;
						}
						vid.play();
					}, function() {
						//insertAltVideo(vid);
						insertAltImage();
						document.getElementById('gum').className = "hide";
						document.getElementById('nogum').className = "nohide";
						alert("There was some problem trying to fetch video from your webcam, using a static image instead.");
					});
				} else {
					insertAltImage();
					//insertAltVideo(vid);
					document.getElementById('gum').className = "hide";
					document.getElementById('nogum').className = "nohide";
					alert("Your browser does not seem to support getUserMedia, using a static image instead.");
				}
				
				vid.addEventListener('canplay', enablestart, false);

				function startDemo() {
					// start video
					vid.play();
					// start tracking
					ctrack.start(vid);
					//start drawing faces
					drawLoop();
				}

				var positions;
				var fd = new faceDeformer();
				fd.init(document.getElementById('webgl'));
				
				document.addEventListener("clmtrackrIteration", function(event) {
					stats.update();
				}, false);
				
				function drawLoop() {
					// track in video
					positions = ctrack.getCurrentPosition();
					overlayCC.clearRect(0, 0, 720, 576);
					if (positions) {
						ctrack.draw(overlay);
					}
					
					// hide buttons
					elem = document.getElementById('buttons');
					elem.setAttribute('class', 'hide');
					// show message
					var scoreel = document.getElementById('score');
					scoreel.innerHTML = "Please keep head still while model fits";
					
					var pn = ctrack.getConvergence();
					if (pn < 1.8) {
						requestAnimFrame(setupFaceDeformation);
						scoreel.innerHTML = "";
						if (vid.tagName == "VIDEO") {
							vid.pause();
						}
					} else {
						requestAnimFrame(drawLoop);
					}
				}
				
				var ph, gui;
				var rotation = 0;
				var scale = 3;
				var xOffset = -10;
				var yOffset = 0;

				function setupFaceDeformation() {
					// draw face deformation model
					positions = ctrack.getCurrentPosition();
					overlayCC.clearRect(0, 0, 720, 576);
					ctrack.draw(overlay);
					fd.load(vid, positions, pModel);
					fd.draw(positions);
					
					// hide video
					var elem = document.getElementById('container');
					elem.setAttribute('class', 'hide');
					// show facial deformation element
					elem = document.getElementById('webglcontainer');
					elem.setAttribute('class', 'nohide');
					// hide message element
					document.getElementById('score').setAttribute('class', 'hide');

					// set up controls
					ph = new parameterHolder();
					gui = new dat.GUI();
					var guiSelect = gui.add(ph, 'presets', presets);
					var gui1 = gui.add(ph, 'param1', -50, 50).listen();
					var gui2 = gui.add(ph, 'param2', -20, 20).listen();
					var gui3 = gui.add(ph, 'param3', -20, 20).listen();
					var gui4 = gui.add(ph, 'param4', -20, 20).listen();
					var gui5 = gui.add(ph, 'param5', -20, 20).listen();
					var gui6 = gui.add(ph, 'param6', -20, 20).listen();
					var gui7 = gui.add(ph, 'param7', -20, 20).listen();
					var gui8 = gui.add(ph, 'param8', -20, 20).listen();
					var gui9 = gui.add(ph, 'param9', -20, 20).listen();
					var gui10 = gui.add(ph, 'param10', -20, 20).listen();
					var gui11 = gui.add(ph, 'param11', -20, 20).listen();
					var gui12 = gui.add(ph, 'param12', -20, 20).listen();
					var gui13 = gui.add(ph, 'param13', -20, 20).listen();
					var gui14 = gui.add(ph, 'param14', -20, 20).listen();
					var gui15 = gui.add(ph, 'param15', -20, 20).listen();
					var gui16 = gui.add(ph, 'param16', -20, 20).listen();
					var gui17 = gui.add(ph, 'param17', -20, 20).listen();
					var gui18 = gui.add(ph, 'param18', -20, 20).listen();
					var gui19 = gui.add(ph, 'param19', -20, 20).listen();
					var gui20 = gui.add(ph, 'param20', -20, 20).listen();
					var guiGrid = gui.add(ph, 'draw_grid', false);
					var guiFace = gui.add(ph, 'draw_face', true);
					
					gui1.onChange(drawDeformedFace);
					gui2.onChange(drawDeformedFace);
					gui3.onChange(drawDeformedFace);
					gui4.onChange(drawDeformedFace);
					gui5.onChange(drawDeformedFace);
					gui6.onChange(drawDeformedFace);
					gui7.onChange(drawDeformedFace);
					gui8.onChange(drawDeformedFace);
					gui9.onChange(drawDeformedFace);
					gui10.onChange(drawDeformedFace);
					gui11.onChange(drawDeformedFace);
					gui12.onChange(drawDeformedFace);
					gui13.onChange(drawDeformedFace);
					gui14.onChange(drawDeformedFace);
					gui15.onChange(drawDeformedFace);
					gui16.onChange(drawDeformedFace);
					gui17.onChange(drawDeformedFace);
					gui18.onChange(drawDeformedFace);
					gui19.onChange(drawDeformedFace);
					gui20.onChange(drawDeformedFace);
					guiSelect.onChange(switchDeformedFace);
					guiGrid.onChange(drawDeformedFace);
					guiFace.onChange(drawDeformedFace);

					drawDeformedFace();
				}

				function drawDeformedFace() {
					// draw model
					var parameters = ctrack.getCurrentParameters();
					parameters[0] = scale*Math.cos(rotation)-1;
					parameters[1] = scale*Math.sin(rotation);
					parameters[2] = xOffset;
					parameters[3] = yOffset;
					parameters[0+4] = ph.param1;
					parameters[1+4] = ph.param2;
					parameters[2+4] = ph.param3;
					parameters[3+4] = ph.param4;
					parameters[4+4] = ph.param5;
					parameters[5+4] = ph.param6;
					parameters[6+4] = ph.param7;
					parameters[7+4] = ph.param8;
					parameters[8+4] = ph.param9;
					parameters[9+4] = ph.param10;
					parameters[10+4] = ph.param11;
					parameters[11+4] = ph.param12;
					parameters[12+4] = ph.param13;
					parameters[13+4] = ph.param14;
					parameters[14+4] = ph.param15;
					parameters[15+4] = ph.param16;
					parameters[16+4] = ph.param17;
					parameters[17+4] = ph.param18;
					parameters[18+4] = ph.param19;
					parameters[19+4] = ph.param20;
					positions = fd.calculatePositions(parameters, true);
					fd.clear();
					if (ph.draw_face) fd.draw(positions);
					if (ph.draw_grid) fd.drawGrid(positions);
				}

				function switchDeformedFace() {
					// draw model
					var parameters = ctrack.getCurrentParameters();
					parameters[0] = scale*Math.cos(rotation)-1;
					parameters[1] = scale*Math.sin(rotation);
					parameters[2] = xOffset;
					parameters[3] = yOffset;
					var split = ph.presets.split(",");
					parameters[0+4] = ph.param1 = parseInt(split[0],10);
					parameters[1+4] = ph.param2 = parseInt(split[1],10);
					parameters[2+4] = ph.param3 = parseInt(split[2],10);
					parameters[3+4] = ph.param4 = parseInt(split[3],10);
					parameters[4+4] = ph.param5 = parseInt(split[4],10);
					parameters[5+4] = ph.param6 = parseInt(split[5],10);
					parameters[6+4] = ph.param7 = parseInt(split[6],10);
					parameters[7+4] = ph.param8 = parseInt(split[7],10);
					parameters[8+4] = ph.param9 = parseInt(split[8],10);
					parameters[9+4] = ph.param10 = parseInt(split[9],10);
					parameters[10+4] = ph.param11 = parseInt(split[10],10);
					parameters[11+4] = ph.param12 = parseInt(split[11],10);
					parameters[12+4] = ph.param13 = parseInt(split[12],10);
					parameters[13+4] = ph.param14 = parseInt(split[13],10);
					parameters[14+4] = ph.param15 = parseInt(split[14],10);
					parameters[15+4] = ph.param16 = parseInt(split[15],10);
					parameters[16+4] = ph.param17 = parseInt(split[16],10);
					parameters[17+4] = ph.param18 = parseInt(split[17],10);
					parameters[18+4] = ph.param19 = parseInt(split[18],10);
					parameters[19+4] = ph.param20 = parseInt(split[19],10);
					positions = fd.calculatePositions(parameters, true);
					if (ph.draw_face) fd.draw(positions);
					if (ph.draw_grid) fd.drawGrid(positions);
				}

				var parameterHolder = function() {
					this.param1 = 0.0001;
					this.param2 = 0.0001;
					this.param3 = 0.0001;
					this.param4 = 0.0001;
					this.param5 = 0.0001;
					this.param6 = 0.0001;
					this.param7 = 0.0001;
					this.param8 = 0.0001;
					this.param9 = 0.0001;
					this.param10 = 0.0001;
					this.param11 = 0.0001;
					this.param12 = 0.0001;
					this.param13 = 0.0001;
					this.param14 = 0.0001;
					this.param15 = 0.0001;
					this.param16 = 0.0001;
					this.param17 = 0.0001;
					this.param18 = 0.0001;
					this.param19 = 0.0001;
					this.param20 = 0.0001;
					this.presets = 0;
					this.draw_face = true;
					this.draw_grid = false;
				}

				var presets = {
					"default" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					"oi mate" : [0, 0, 13, 1.2, 0, -15, 0, 1, 8, -5, 0, 0, 0, 0, 0, 0, 0, 11.6, 0, -7],
					"unhappy" : [0, 0, 0, 0, 0, 0, 0, 0, 0, -13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					"greek" : [0, 0, 0, 1.6, 0, -6, 0, 0, 0, -13, 0, 4.7, 1, 0, 11, -1, 8, 8, 0, 0],
					"cheery" : [0, 0, 0, 0, 10.7, 0, 16.8, 0, 0, -5, 0, -4, 13, 0, 0, 0, 0, 0, 0, 0],
					"luke" : [0, 0, -1.7, -8.7, -8, -4.8, 12.5, -1, 14.6, -11, 0, -2, -13, 0, 0, 0, 0, 7, 0, -3],
					"chum" : [0, 0, 13, 1.2, 0, 2.5, 0, 1, 16.8, -5, 0, 0, 0, 0, 0, 0, 0, 11.6, 0, -7],
					"disgust" : [-4, -14, 8, 2, 3, -5.6, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -10, 0, -5],
				};
			</script>
		</div>
	</body>
		<script type="text/javascript" src="javascripts/materialize.min.js"></script>
		<script>
		 $(document).ready(function(){
		    $('ul.tabs').tabs();
		  });
		</script>
		<script>
		 $(document).ready(function(){
		    // the "href" attribute of .modal-trigger must specify the modal ID that wants to be triggered
		    $('.modal-trigger').leanModal();
		  });
		</script>
</html>
